package org.jsets.fastboot.uid.config;

import java.util.Objects;
import javax.sql.DataSource;
import org.jsets.fastboot.util.StringUtils;
import org.jsets.fastboot.uid.impl.AssignWorkerIdAssigner;
import org.jsets.fastboot.uid.impl.JdbcWorkerIdAssigner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import com.alibaba.druid.pool.DruidDataSource;
import com.baidu.fsg.uid.UidGenerator;
import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import lombok.extern.slf4j.Slf4j;

/**
 * UID生成器配置
 */
@Slf4j
@Configuration
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
@EnableConfigurationProperties({ UidGeneratorProperties.class })
@ConditionalOnProperty(prefix = UidGeneratorProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class UidGeneratorAutoConfiguration {

	@Autowired
	private UidGeneratorProperties properties;

	@Autowired
	private ApplicationContext applicationContext;

	@Bean
	public WorkerIdAssigner workerIdAssigner() {
		if (StringUtils.hasText(this.properties.getDriverClassName())
				&& StringUtils.hasText(this.properties.getUrl())
				&& StringUtils.hasText(this.properties.getUsername())
				&& StringUtils.hasText(this.properties.getPassword())) {

			final DruidDataSource dataSource = new DruidDataSource();
			dataSource.setDriverClassName(this.properties.getDriverClassName());
			dataSource.setUrl(this.properties.getUrl());
			dataSource.setUsername(this.properties.getUsername());
			dataSource.setPassword(this.properties.getPassword());
			final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
			return new JdbcWorkerIdAssigner(jdbcTemplate, this.properties.getSchema());
		}

		if (Objects.nonNull(this.properties.getWorkerId())) {
			return new AssignWorkerIdAssigner(this.properties.getWorkerId());
		}

		DataSource dataSource = null;
		try {
			dataSource = this.applicationContext.getBean(DataSource.class);
		} catch (Exception e) {
			log.warn(e.getMessage());
		}
		if (Objects.nonNull(dataSource)) {
			final JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
			return new JdbcWorkerIdAssigner(jdbcTemplate, this.properties.getSchema());
		}
		throw new IllegalStateException("请正确设置[worker-id-assigner]属性");
	}

	@Bean
	public UidGenerator uidGenerator(WorkerIdAssigner workerIdAssigner) {
		CachedUidGenerator generator = new CachedUidGenerator();
		generator.setWorkerIdAssigner(workerIdAssigner);
		
		if (this.properties.getTimeBits() > 0) {
			generator.setTimeBits(this.properties.getTimeBits());
		}
		if (this.properties.getWorkerBits() > 0) {
			generator.setWorkerBits(this.properties.getWorkerBits());
		}
		if (this.properties.getSeqBits() > 0) {
			generator.setSeqBits(this.properties.getSeqBits());
		}
		if (StringUtils.hasText(this.properties.getEpochStr())) {
			generator.setEpochStr(this.properties.getEpochStr());
		}
		if (this.properties.getBoostPower() > 0) {
			generator.setBoostPower(this.properties.getBoostPower());
		}
		if (this.properties.getPaddingFactor() > 0) {
			generator.setPaddingFactor(this.properties.getPaddingFactor());
		}
		if (this.properties.getScheduleInterval() > 0) {
			generator.setScheduleInterval(this.properties.getScheduleInterval());
		}

		return generator;
	}
}